const path = require('path') // nodeJS 核心模块，处理路径
const ESLintPlugin = require('eslint-webpack-plugin') // ESLint 插件
const HtmlWebpackPlugin = require('html-webpack-plugin'); // HTML 打包插件
const { resolve } = require('path');

module.exports = {
    // Webpack 打包入口
    entry: './src/main.js', // 相对路径运行在命令行所在的目录，不需要处理
    // Webpack 打包输出位置
    // output: {
    //     // 文件输出路径
    //     path: undefined, // 开发环境不需要文件输出，直接清空输出结果

    // },
    // 加载器
    module: {
        rules: [ // 打包时每个文件都会经过所有 loader 处理
            {
                oneOf: [ // 只能匹配上一个 loader, 剩下的就不匹配了。
                    // 加载器配置
                    {
                        test: /\.css$/, // 匹配以 .css 结尾的文件
                        //loader: 'css-loader', // 只能设置单个 loader
                        use: [  // 设置多个 loader
                            "style-loader", // 将 js 中 css 通过创建 style 标签的方式添加到 html 文件中生效
                            "css-loader" // 将 css 资源编译成 commonJS 的模块到 js 中
                        ], // 使用指定的加载器处理该文，执行顺序：从数组的末位执行到初位
                    },
                    {
                        test: /\.less$/,
                        use: [
                            'style-loader',
                            'css-loader',
                            'less-loader', // compiles Less to CSS
                        ],
                    },
                    {
                        test: /\.s[ac]ss$/,
                        use: [
                            'style-loader',
                            'css-loader',
                            'sass-loader', // 将 Sass 编译成 CSS
                        ],
                    },
                    {
                        test: /\.styl$/,
                        use: [
                            'style-loader',
                            'css-loader',
                            'stylus-loader', // 将 Stylus 编译成 CSS
                        ],
                    },
                    {
                        test: /\.(png|jpe?g|gif|webp)$/,  // 处理图片
                        type: 'asset',
                        parser: {
                            dataUrlCondition: {
                                maxSize: 10 * 1024 // 小于 10kb 的图片会被解析成 base64 放在 url 中。 优点：减少请求数量 缺点：文件体积会变大
                            }
                        },
                        generator: {
                            // 将图片文件输出到 static/imgs 目录中
                            // 将图片文件命名 [hash:8][ext][query]
                            // [hash:8]: hash值取8位
                            // [ext]: 使用之前的文件扩展名
                            // [query]: 添加之前的query参数
                            filename: "static/imgs/[hash:8][ext][query]",
                        }
                    },
                    {
                        test: /\.(ttf|woff2?|mp3|mp4|avi)$/,  // 处理图标 音视频等其他类型文件（不需要处理，只原封不动地输出）
                        type: 'asset/resource',
                        generator: {
                            // 将图标文件输出到 static/media 目录中
                            // 将图标文件命名 [hash:8][ext][query]
                            // [hash:8]: hash值取8位
                            // [ext]: 使用之前的文件扩展名
                            // [query]: 添加之前的query参数
                            filename: "static/media/[hash:8][ext][query]",
                        }
                    },
                    {
                        test: /\.m?js$/, // 处理 js
                        //exclude: /(node_modules|bower_components)/, // 排除 node_module 内的 js 代码 
                        include: path.resolve(__dirname, '../src'), // 仅打包 ../src 文件夹下的代码
                        use: {
                            loader: 'babel-loader', // 使用 babel 编译器
                            options: { //可使用 options 指定 babel 规则，也可以不写，通过配置文件设置 babel 规则
                                //presets: ['@babel/preset-env'] // 使用预设
                                cacheDirectory: true, // 打开 babel 编译缓存，使用缓存避免未改动代码重复编译，从而提升打包速度
                                cacheCompression: false, // 缓存压缩，不压缩以提高打包速度
                                plugins: ['@babel/plugin-transform-runtime'] // 禁用 bable 对每个文件的垫片功能代码注入，所有使用的辅助代码片段从 @babel/plugin-transform-runtime 中直接引用，统一辅助代码片段在不同的文件中重复定义
                            }
                        }
                    }
                ]
            }

        ]
    },
    // 插件
    plugins: [
        new ESLintPlugin({  // ESLint 语法检查插件
            context: path.resolve(__dirname, '../src'), //绝对路径需要注意：由于该文件在文件夹内，__dirname为文件夹路径，需要往外退一个层级
            exclude: 'node_modules', // 不去检查 node_modules 里的代码，默认配置，可不写
            cache: true, // 打开 Lint 缓存，对未修改的代码使用缓存中的检查结果，提升打包速度
            cacheLocation: path.resolve(__dirname, '../node_modules/.cache/.eslintcahce') // 缓存文件存放目录
        }),
        new HtmlWebpackPlugin({ // 自动生成 HTML 资源，并且引入打包的 js
            template: path.resolve(__dirname, '../public/index.html') // 使用指定路径的 HTML 文件作为模板，生成的 HTML 资源跟模板相同，并且引入了打包的 js 资源
        })
    ],
    // 模式：
    // -- development: 1.打包代码
    // -- production: 1.打包代码 2.压缩代码
    mode: 'development',
    // 开启 devServer (开启服务器，打包代码，暴露资源，修改源码后，自动重新打包，刷新浏览器)
    // 开启 server 指令：npx webpack-dev-server
    // 只会在内存中编译打包，不会有任何输出
    devServer: {
        host: 'localhost',
        port: 3000, // 指定 devServer 端口
        open: true, // 自动打开浏览器
        compress: true,  // 启用 gzip compression 压缩代码
        hot: true // 是否打开 Hot Module Replacement 热模块更新（当文件发生更改时，只重新打包替换更改的打包模块，不全局重新打包以提升打包速度。注意：该选项默认为 true，且不对 js 代码生效。）
    },
    devtool: "cheap-module-source-map", // 生成编译后代码和源代码的映射文件(*.map)，报错时可以定位到源文件的行映射，编译速度快
}